package com.xiyuan.smartutils.client.http;

import com.xiyuan.smartutils.StrUtils;

import java.util.*;

/**
 * The Class HttpHeader.
 *
 * @author xiyuan
 */
public class HttpHeader {
    private static final String HEADER_SEPARATOR = ", ";
    private static final String HEADER_VALUE_SEPARATOR = "; ";
    
    
    /**
     * The header map.
     */
    private final SortedMap<String, List<String>> headerMap = new TreeMap<String, List<String>>();
    private final transient Map<String, String> configMap = new LinkedHashMap<>(2);
    
    /**
     * Instantiates a new http response headers.
     */
    public HttpHeader() {
        setValueSeparator("Cookie", HEADER_VALUE_SEPARATOR);
    }
    
    private String getName(String name) {
        return StrUtils.trimToEmpty(configMap.get(StrUtils.trimToEmpty(name).toLowerCase()));
    }
    
    private String setName(String name) {
        name = StrUtils.trimToEmpty(name).toLowerCase();
        if (!name.isEmpty()) configMap.put(name, name);
        return name;
    }
    
    private String removeName(String name) {
        name = StrUtils.trimToEmpty(name).toLowerCase();
        configMap.remove(name);
        return name;
    }
    
    public String getHeaderSeparator(String name) {
        String sp = configMap.getOrDefault("$SEPARATOR:" + (name == null ? "" : name.toLowerCase()), HEADER_SEPARATOR);
        
        
        return sp == null || sp.isEmpty() ? HEADER_SEPARATOR : sp;
    }
    
    public void setValueSeparator(String name, String separator) {
        if (separator == null || name == null || name.isEmpty()) {
            return;
        }
        configMap.put("$SEPARATOR:" + name.trim().toLowerCase(), StrUtils.trim(separator));
    }
    
    /**
     * Gets the header value.
     *
     * @param name the name
     * @return the header value
     */
    public String getHeader(String name) {
        List<String> list = headerMap.get(getName(name));
        if (list == null) {return null;}
        return String.join(getHeaderSeparator(name), list);
    }
    
    /**
     * Gets the header values.
     *
     * @param name the name
     * @return the header values
     */
    public List<String> getHeaders(String name) {
        List<String> list = headerMap.get(getName(name));
        if (list == null) {
            return null;
        }
        return Collections.unmodifiableList(list);
    }
    
    /**
     * Contains header.
     *
     * @param name the header name
     * @return true, if successful
     */
    public boolean containsHeader(String name) {
        return configMap.containsKey(getName(name));
    }
    
    /**
     * Adds the header.
     *
     * @param name  the name
     * @param value the value
     */
    public void addHeader(String name, String value) {
        if (StrUtils.isEmpty(name) && StrUtils.isEmpty(value)) return;
        List<String> list = headerMap.computeIfAbsent(setName(name), k -> new ArrayList<>(2));
        String[] ls = value.split(getHeaderSeparator(name));
        list.addAll(Arrays.asList(ls));
    }
    
    /**
     * Removes the header.
     *
     * @param name the name
     */
    public String removeHeader(String name) {
        String value = getHeader(removeName(name));
        headerMap.remove(name);
        
        return value;
    }
    
    /**
     * Gets the header names.
     *
     * @return the header names
     */
    public List<String> getHeaderNames() {
        return new ArrayList<String>(headerMap.keySet());
    }
    
    public Set<Map.Entry<String, List<String>>> entrySet() {
        return headerMap.entrySet();
    }
    
}
